using SeaVM;
using System;

namespace SeaVM.Instructions
{
    /*
    *   push data
    *   push define
    *   push address
    */
    public class Push
    {
        public static Instruction Create(Data data)
        {
            Instruction inst = new Instruction(Opcode.Push);
            InstructionArg arg1 = new InstructionArg(data);
            inst.args.Add(arg1);
            return inst;
        }

        public static Instruction Create(int address)
        {
            Instruction inst = new Instruction(Opcode.Push);
            InstructionArg arg1 = new InstructionArg(address,InstructionArgType.Address);
            inst.args.Add(arg1);
            return inst;
        }

        public static Instruction Create(string define)
        {
            Instruction inst = new Instruction(Opcode.Push);
            InstructionArg arg1 = new InstructionArg(define,InstructionArgType.Define);
            inst.args.Add(arg1);
            return inst;
        }

        public static void Run(VM vm,Instruction inst)
        {
            InstructionArg arg1 = inst.args[0];
            switch(arg1.type)
            {
                case InstructionArgType.Address:
                {
                    Instructions.AssertAddress(vm,arg1.address);
                    Data data = vm.memory.Read(arg1.address);
                    vm.stack.Push(data);
                    break;
                }
                case InstructionArgType.Data:
                {
                    Data data = arg1.data;
                    vm.stack.Push(data);
                    break;
                }
                case InstructionArgType.Define:
                {
                    Instructions.AssertDefine(vm,arg1.define);
                    Instructions.AssertAddress(vm,vm.defines[arg1.define]);
                    Data data = vm.memory.Read(vm.defines[arg1.define]);
                    vm.stack.Push(data);
                    break;
                }
                default:throw new VmRunError("Push指令形式错误");
            }
            vm.line++;
        }
    }
}